import Immutable from 'immutable';

import {
  queryProvinceList,
  queryCityList,
  queryAreaList,
  queryBrandList,
  queryDistanceList,
  queryStationList,
  searchStation,
  queryCityName,
  queryCurrentStation,
} from '../services/oilStation';
// import toast from '../utils/toast';
import shellLogo from '../../assets/images/station/logo_shell.png';
import shLogo from '../../assets/images/station/logo_sh.png';

const OilStationRecord = Immutable.Record({
  lat: null,
  lng: null,
  name: null,
  distance: null,
  mchId: null,
  phone: null,
  address: null,
  selected: false,
  id: null,
});

export class OilStation extends OilStationRecord {
  getKm() {
    let km;
    if (this.get('distance')) {
      km = `${(this.get('distance') / 1000).toFixed(2)}km`;
    } else {
      km = '';
    }
    return km;
  }
  getLogo() {
    let logo;
    if (this.get('mchId') === '66') {
      logo = shellLogo;
    } else {
      logo = shLogo;
    }
    return logo;
  }
}

const AddressRecord = Immutable.Record({
  name: null,
  children: Immutable.List(),
  id: null,
  selected: false,
});

export class Address extends AddressRecord {

}

const DistanceRecord = Immutable.Record({
  distance: null,
  name: null,
  selected: false,
});

export class Distance extends DistanceRecord {

}

const BrandRecord = Immutable.Record({
  code: null,
  name: null,
  selected: false,
});

export class Brand extends BrandRecord {
}

export default {
  namespace: 'oilStation',

  state: Immutable.fromJS({
    dataList: {
      list: [],
      hasMore: true,
      page: 1,
    },
    mapList: [],
    searchList: {
      list: [],
      hasMore: true,
      page: 1,
    },
    provinceList: [],
    distanceList: [],
    brandList: [],
    currentCity: '......',
    geoStatus: 'loading',
    currentStation: null,
  }),

  effects: {
    *initData(_, { put }) {
      yield put({
        type: 'fetchProvinceListIfNeeded',
        payload: {
          source: window.source,
        },
      });

      yield put({
        type: 'fetchDistanceListIfNeeded',
        payload: {
          source: window.source,
        },
      });

      yield put({
        type: 'fetchBrandListIfNeeded',
        payload: {
          source: window.source,
        },
      });
      yield put.resolve({
        type: 'doGeoIfNeeded',
      });
    },
    *refreshStationList(_, { select, put }) {
      const geoData = yield select(state => state.global.get('geoData'));
      const brandList = yield select(state => state.oilStation.get('brandList'));
      const distanceList = yield select(state => state.oilStation.get('distanceList'));
      const selectedBrand = brandList.find(brand => brand.get('selected'));
      const selectedDistance = distanceList.find(distance => distance.get('selected'));
      yield put({
        type: 'fetchStationList',
        payload: {
          lat: geoData.get('latitude'),
          lon: geoData.get('longitude'),
          targetPage: 1,
          pageSize: 10,
          source: window.source,
          distance: selectedDistance ? selectedDistance.get('distance') : null,
          brand: selectedBrand && selectedBrand.get('code') !== '0' ? selectedBrand.get('code') : null,
        },
      });
    },
    *fetchCurrentStation({ payload }, { call, put }) {
      const res = yield call(queryCurrentStation, payload);
      if (res.success) {
        yield put({
          type: 'updateCurrentStation',
          payload: res.data,
        });
      }
    },
    *doGeoIfNeeded(_, { put, select }) {
      const geoData = yield select(state => state.global.get('geoData'));
      if (!geoData.get('latitude')) {
        yield put.resolve({
          type: 'doGeo',
        });
      }
    },
    *doGeo({ payload }, { put, select }) {
      const geoDataBefore = yield select(state => state.global.get('geoData'));
      yield put.resolve({
        type: 'global/wxGeo',
      });
      const geoData = yield select(state => state.global.get('geoData'));
      if ((!geoDataBefore.get('latitude') && geoData.get('latitude')) || (payload && payload.force)) {
        yield put({
          type: 'refreshStationList',
        });
      }
      yield put({
        type: 'updateGeoStatus',
        payload: geoData,
      });
      yield put({
        type: 'fetchCityName',
        payload: {
          lat: geoData.get('latitude'),
          lon: geoData.get('longitude'),
          source: window.source,
        },
      });
      yield put({
        type: 'fetchCurrentStation',
        payload: {
          lat: geoData.get('latitude'),
          lon: geoData.get('longitude'),
        },
      });
    },
    *fetchCityName({ payload }, { call, put }) {
      const res = yield call(queryCityName, payload);
      if (res.success) {
        yield put({
          type: 'updateCurrentCity',
          payload: res.data.province,
        });
      }
    },
    *fetchMapList({ payload }, { call, put }) {
      const res = yield call(queryStationList, payload);
      if (res.success) {
        yield put({
          type: 'updateMapList',
          payload: res.data,
        });
      }
    },
    *fetchStationList({ payload }, { call, put }) {
      const res = yield call(queryStationList, payload);
      if (res.success) {
        yield put({
          type: 'updateStationList',
          payload: res.data,
        });
      }
    },
    *searchStation({ payload }, { call, put }) {
      const res = yield call(searchStation, payload);
      if (res.success) {
        yield put({
          type: 'updateSearchList',
          payload: res.data,
        });
      }
    },
    *fetchBrandListIfNeeded({ payload }, { select, call, put }) {
      const brandList = yield select(state => state.oilStation.get('brandList'));
      if (brandList.size === 0) {
        const res = yield call(queryBrandList, payload);
        if (res.success) {
          yield put({
            type: 'updateBrandList',
            payload: res.data,
          });
        }
      }
    },
    *fetchDistanceListIfNeeded({ payload }, { select, call, put }) {
      const distanceList = yield select(state => state.oilStation.get('distanceList'));
      if (distanceList.size === 0) {
        const res = yield call(queryDistanceList, payload);
        if (res.success) {
          yield put({
            type: 'updateDistanceList',
            payload: res.data,
          });
        }
      }
    },
    *fetchProvinceListIfNeeded(_, { select, call, put }) {
      const provinceList = yield select(state => state.oilStation.get('provinceList'));
      if (provinceList.size === 0) {
        const res = yield call(queryProvinceList);
        if (res.success) {
          yield put({
            type: 'updateProvinceList',
            payload: res.data,
          });
        }
      }
    },
    *selectArea({ payload }, { call, put }) {
      const { province, city, area } = payload;
      yield put({
        type: 'updateSelection',
        payload,
      });
      if (!city && province.get('id') !== -1 && province.get('children').size === 0) {
        const res = yield call(queryCityList, { province: province.get('name') });
        if (res.success) {
          yield put({
            type: 'updateCityList',
            payload: {
              list: res.data,
              province,
            },
          });
        }
      } else if (!area && city && city.get('id') !== -1 && city.get('children').size === 0) {
        const res = yield call(queryAreaList, { city: city.get('name') });
        if (res.success) {
          yield put({
            type: 'updateAreaList',
            payload: {
              list: res.data,
              city,
              province,
            },
          });
        }
      }
    },
  },

  reducers: {
    selectFilter(state, { payload }) {
      const { type, value } = payload;
      const name = type === 'brand' ? 'brandList' : 'distanceList';
      let list = state.get(name);
      list = list.map(item => item.set('selected', item.get('name') === value.get('name')));
      return state.set(name, list);
    },
    updateCurrentStation(state, { payload }) {
      const station = payload ? new OilStation({
        id: payload.gasStationId,
      }) : null;
      return state.set('currentStation', station);
    },
    updateGeoStatus(state, { payload }) {
      return state.set('geoStatus', payload.get('latitude') ? 'success' : 'fail');
    },
    updateCurrentCity(state, { payload }) {
      return state.set('currentCity', payload);
    },
    updateMapList(state, { payload }) {
      const list = payload.resultList.map((item) => {
        return new OilStation({
          lat: item.marsLat,
          lng: item.marsLon,
          name: item.gasStationName,
          distance: item.distance,
          mchId: item.mchId,
          phone: item.phone,
          address: item.detailAddr,
          id: item.gasStationId,
        });
      });
      return state.set('mapList', Immutable.fromJS(list).filter(s => s.get('lat') && s.get('lng')));
    },
    updateStationList(state, { payload }) {
      let list = state.getIn(['dataList', 'list']);
      if (payload.targetPage === 1) {
        list = list.clear();
      }

      payload.resultList.forEach((item) => {
        list = list.push(new OilStation({
          lat: item.marsLat,
          lng: item.marsLon,
          name: item.gasStationName,
          distance: item.distance,
          mchId: item.mchId,
          phone: item.phone,
          address: item.detailAddr,
          id: item.gasStationId,
        }));
      });
      return state.mergeIn(['dataList'], {
        hasMore: payload.pageCount > payload.targetPage,
        page: payload.targetPage,
        list,
      });
    },
    updateSearchList(state, { payload }) {
      let list = state.getIn(['searchList', 'list']);
      if (payload.targetPage === 1) {
        list = list.clear();
      }

      payload.resultList.forEach((item) => {
        list = list.push(new OilStation({
          lat: item.marsLat,
          lng: item.marsLon,
          name: item.gasStationName,
          distance: item.distance,
          mchId: item.mchId,
          phone: item.phone,
          address: item.detailAddr,
          id: item.gasStationId,
        }));
      });
      return state.mergeIn(['searchList'], {
        hasMore: payload.pageCount > payload.targetPage,
        page: payload.targetPage,
        list,
      });
    },
    updateCityList(state, { payload }) {
      const { province, list } = payload;
      let provinceList = state.get('provinceList');
      const pIndex = provinceList.findIndex(p => p.get('name') === province.get('name'));
      let cList = Immutable.fromJS(list.map(item => new Address({ name: item.city })));
      cList = cList.insert(0, new Address({ name: '全部', id: -1 }));
      provinceList = provinceList.setIn([pIndex, 'children'], cList);
      return state.set('provinceList', provinceList);
    },
    updateAreaList(state, { payload }) {
      const { province, city, list } = payload;
      let provinceList = state.get('provinceList');
      const pIndex = provinceList.findIndex(p => p.get('name') === province.get('name'));
      const cIndex = provinceList.getIn([pIndex, 'children']).findIndex(c => c.get('name') === city.get('name'));
      console.log('======', pIndex, cIndex);
      let aList = Immutable.fromJS(list.map(item => new Address({ name: item.district })));
      aList = aList.insert(0, new Address({ name: '全部', id: -1 }));
      provinceList = provinceList.setIn([pIndex, 'children', cIndex, 'children'], aList);
      return state.set('provinceList', provinceList);
    },
    updateSelection(state, { payload }) {
      const { province, city, area } = payload;
      let provinceList = state.get('provinceList');
      provinceList = provinceList.map(p => p.set('selected', p === province));
      if (city) {
        const pIndex = provinceList.findIndex(p => p.get('name') === province.get('name'));
        let cityList = provinceList.getIn([pIndex, 'children']);
        cityList = cityList.map(c => c.set('selected', c.get('name') === city.get('name')));
        provinceList = provinceList.setIn([pIndex, 'children'], cityList);
        if (area) {
          const cIndex = cityList.findIndex(c => c.get('name') === city.get('name'));
          let areaList = cityList.getIn([cIndex, 'children']);
          areaList = areaList.map(a => a.set('selected', a.get('name') === area.get('name')));
          provinceList = provinceList.setIn([pIndex, 'children', cIndex, 'children'], areaList);
        }
      }
      return state.set('provinceList', provinceList);
    },
    updateBrandList(state, { payload }) {
      let brandList = Immutable.fromJS(payload.map(item => new Brand(item)));
      brandList = brandList.insert(0, new Brand({ code: '0', name: '全部品牌' }));
      return state.set('brandList', brandList);
    },
    updateDistanceList(state, { payload }) {
      let list = Immutable.fromJS(payload.map(item => new Distance(item)));
      list = list.sort((pre, next) => {
        return pre.get('distance') > next.get('distance') ? 1 : 0;
      });
      list = list.setIn([list.size - 1, 'selected'], true);
      return state.set('distanceList', list);
    },
    updateProvinceList(state, { payload }) {
      let list = Immutable.fromJS(payload.map(item => new Address({ name: item.province })));
      list = list.insert(0, new Address({ name: '全部', id: -1 }));
      return state.set('provinceList', list);
    },
  },
  subscriptions: {
    stepup({ dispatch }) {
      document.addEventListener('visibilitychange', () => {
        console.log('页面可见状态变化', document.hidden);
        if (!document.hidden && ['/cq/home', '/station/'].some(url => window.location.href.indexOf(url) !== -1)) {
          dispatch({
            type: 'doGeo',
            payload: { force: true },
          });
        }
      });
    },
  },
};
